<?php

namespace App\Http\Controllers\Example;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use TestFacades;
use DB;
use App\Exceptions\QueryException;
use Exception;
use QrCode;
use App\Admin;
//监听
use App\Events\TestEvent;
use Encrypt;
use Zipper;

class TestController extends Controller 
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */


    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    ///服务提供者和门面
    public function test()
    {  
        echo '服务容器'."</br>";
        //服务容器
        $a=app('test');
        //
        echo $a->test()."</br>";

        echo '门面'."</br>";
        //服务提供者更进一步就是门面，比服务容器更加方便
        echo TestFacades::test()."</br>";
        try {
           throw new QueryException("Error Processing Request", 1);
           
        } catch (QueryException $e) {
            echo "测试抛出异常"."</br>";
        }catch (Exception $e){
            echo "11"."</br>";
        }
        $admin=Admin::find(1);

        
    }
    //生成二维码图片并下载
    public function QrCode()
    {
        //使用二维码包生成图片
        $qrcode_url=public_path('qrcodes/qrcode.png');
        $logo_url='/public/qrcode_logo.png';

        if(!file_exists(dirname($qrcode_url)))$this->create_folders(dirname($qrcode_url));
        if(!file_exists(dirname($logo_url)))$this->create_folders(dirname($logo_url));//仅png支持logo;

        QrCode::format('png')->size(500)->merge($logo_url,.15)->generate('LaravelAcademy',$qrcode_url);

        //打包路径生成在项目的public目录下
        Zipper::make('public/test.zip')->add(public_path('qrcodes'))->close();

        $this->downLoad();
    }

    //没有文件夹则创建
    public function create_folders($dir){ 
        return is_dir($dir) or ($this->create_folders(dirname($dir)) and mkdir($dir, 0777, true)); 
    }


    public function downLoad(){

        
        $file=public_path("qrcodes/qrcode.png");//取绝对路径
        
        if(!file_exists($file)){
            echo "资源已删除";exit;
        }
        ob_clean();
        Header("Content-type: application/octet-stream"); 
        Header("Accept-Ranges: bytes"); 
        Header("Accept-Length: ".filesize($file)); 
        Header("Content-Disposition: attachment; filename=\"".basename($file)."\"");
        readfile($file);

        @unlink($file);
    }

    //TestImpl  TestTrait 接口
    public function TestTrait(){
        $Admin=Admin::find(1);
        $a=$Admin->test();
        echo $a;
    }

    public function testListenter(){
        event(new TestEvent('TestListeners'));
    }

    public function encrypt(){
       
        $rsa=new Encrypt();
        
        echo "待加密数据：segmentfault.com"."</br>";
        $pre = $rsa::privEncrypt("segmentfault.com");
        echo "加密后的密文:\n" . $pre . "\n";
        $pud = $rsa::pubDecrypt($pre);
        echo "解密后数据:" . $pud . "\n"."</br>";

        echo "</br>";
        
        echo "待加密数据：segmentfault.com"."</br>";
        $pue = $rsa::pubEncrypt("segmentfault.com");
        echo "加密后的密文:\n" . $pue . "\n";
        $prd = $rsa::privDecrypt($pue);
        echo "解密后数据:" . $prd;
    }

    public function service(){
        /*$_SERVER["REQUEST_METHOD"]  请求当前PHP页面的方法
        $_SERVER["REQUEST_URI"] 请求的URI
        $_SERVER["SERVER_SOFTWARE"] 用的是哪一种服务器
        $_SERVER["REMOTE_ADDR"] 客户的IP地址
        $_SERVER["SERVER_ADDR"] 当前服务器的IP地址
        $_SERVER["SCRIPT_FILENAME"] 主前请求文件的路径
        $_SERVER["HTTP_USER_AGENT"] 当前访问这个网址的电脑和浏览器的情况
        $_SERVER["HTTP_REFERER"]    上级来源（用户从哪个地址进入当前网页的）
        $_SERVER["REQUEST_TIME"]    当前的时间*/
    }

    public function a(){
       /* abs()   求绝对值    $abs = abs(-4.2); //4.2 数字  绝对值数字
        ceil()  进一法取整   echo ceil(9.999); // 10 浮点数 进一取整
        floor() 舍去法取整   echo floor(9.999); // 9 浮点数 直接舍去小数部分
        fmod()  浮点数取余   "$x = 5.7;$y = 1.3;$r = fmod($x, $y);// $r equals 0.5, because 4 *  1.3 + 0.5 = 5.7    "    两个浮点数,x>y   浮点余数
        pow()   返回数的n次方 echo pow(-1, 20); // 1  基础数 n次方 乘方值
        round() 浮点数四舍五入 echo round(1.95583, 2);// 1.96  一个数值    保留小数点后多少位,默认为0 舍入后的结果
        sqrt()  求平方根    echo sqrt(9); //3   被开方的数   平方根
        max()   求最大值    "echo max(1, 3, 5, 6, 7);  // 7 echo max(array(2, 4, 5)); // 5" 多个数字或数组 返回其中的最大值
        min()   求最小值    min 多个数字或数组 返回其中的最小值
        mt_rand()   更好的随机数  echo mt_rand(0,9);//n   最小/最大,随机数   随机返回范围内的值
        rand()  随机数 echo rand() 最小/最大,随机数   随机返回范围内的值
        pi()    获取圆周率值  echo pi(); // 3.1415926535898   无   获取圆周率*/
    }

    public function b(){
        //开始时间
        $time_start = microtime(true);
        /*
        xxxxxxxxxxxxxxxxxxxc程序
         */
        //结整时间
        $time_end = microtime(true);
        //相减得到运行时间
        $time = $time_end - $time_start;
    }

    public function c(){
        /*trim()  删除字符串两端的空格或其他预定义字符  "$str = "\r\nHello World!\r\n"; echo trim($str);
        rtrim() 删除字符串右边的空格或其他预定义字符  "$str = "Hello World!\n\n"; echo rtrim($str);"
        chop()  rtrim()的别名  同上
        ltrim() 删除字符串左边的空格或其他预定义字符  "$str = "\r\nHello World!"; echo ltrim($str);"
        dirname()   回路径中的目录部分（我们把它归在了字符串函数里了）   echo dirname("c:/testweb/home.php");
        str_pad()   把字符串填充为指定的长度    $str = "Hello World"; echo str_pad($str,20,".");
        str_repeat()    重复使用指定字符串   echo str_repeat(".",13);
        str_split() 把字符串分割到数组中  print_r(str_split("Hello"));
        strrev()    反转字符串   echo strrev("Hello World!");
        wordwrap()  按照指定长度对字符串进行折行处理    "$str = ""An example on a long word is: Supercalifragulistic""; echo wordwrap($str,15);"
        str_shuffle()   随机地打乱字符串中所有字符   echo str_shuffle("Hello World");
        parse_str() 将字符串解析成变量   "parse_str("id=23&name=John%20Adams",$myArray); print_r($myArray);"
        number_format() 通过千位分组来格式化数字    "echo number_format("1000000"); echo number_format("1000000",2); echo number_format("1000000",2,"","",""."");"
        strtolower()    字符串转为小写 echo strtolower("Hello WORLD!");
        strtoupper()    字符串转为大写 echo strtoupper("Hello WORLD!");
        ucfirst()   字符串首字母大写    echo ucfirst("hello world");
        ucwords()   字符串每个单词首字符转为大写  echo ucwords("hello world");
        htmlentities()  把字符转为HTML实体 $str = ""John & 'Adams'""; echo htmlentities($str, ENT_COMPAT);
        htmlspecialchars()  预定义字符转html编码    
        nl2br() \n转义为
        标签  echo nl2br("One line.\nAnother line.");
        strip_tags()    剥去 HTML、XML 以及 PHP 的标签  echo strip_tags("Hello world!");
        addcslashes()   在指定的字符前添加反斜线转义字符串中字符    $str = ""Hello, my name is John Adams." echo $str; echo addcslashes($str,'m');"
        stripcslashes() 删除由addcslashes()添加的反斜线  echo stripcslashes("Hello, \my na\me is Kai Ji\m.");
        addslashes()    指定预定义字符前添加反斜线   $str = "Who's John Adams?";echo addslashes($str);
        stripslashes()  删除由addslashes()添加的转义字符  echo stripslashes("Who\'s John Adams?");
        quotemeta() 在字符串中某些预定义的字符前添加反斜线 $str = "Hello world. (can you hear me?)"; echo quotemeta($str);
        chr()   从指定的 ASCII 值返回字符    echo chr(052);
        ord()   返回字符串第一个字符的 ASCII值  echo ord("hello");
        strcasecmp()    不区分大小写比较两字符串    echo strcasecmp("Hello world!","HELLO WORLD!");
        strcmp()    区分大小写比较两字符串 
        strncmp()   比较字符串前n个字符,区分大小写    
        strncasecmp()   比较字符串前n个字符,不区分大小写   int strncasecmp ( string $str1 , string $str2 , int $len )
        strnatcmp() 自然顺序法比较字符串长度,区分大小写  int strnatcmp ( string $str1 , string $str2 )
        strnatcasecmp() 自然顺序法比较字符串长度,不区分大小写 int strnatcasecmp ( string $str1 , string $str2 )
        chunk_split()   将字符串分成小块    str chunk_split(str $body[,int $len[,str $end]])
        strtok()    切开字符串   str strtok(str $str,str $token)
        explode()   使用一个字符串为标志分割另一个字符串  array explode(str $sep,str $str[,int $limit])
        implode()   同join,将数组值用预订字符连接成字符串   string implode ( string $glue , array $pieces )
        substr()    截取字符串   string substr ( string $string , int $start [, int $length ] )
        str_replace()   字符串替换操作,区分大小写   mix str_replace(mix $search,,mix $replace,mix $subject[,int &$num])
        str_ireplace()  字符串替换操作,不区分大小写  mix str_ireplace ( mix $search , mix $replace , mix $subject [, int &$count ] )
        substr_count()  统计一个字符串,在另一个字符串中出现次数    int substr_count ( string $haystack , string $needle [, int $offset = 0 [, int $length ]] )
        substr_replace()    替换字符串中某串为另一个字符串 mixed substr_replace ( mixed $string , string $replacement , int $start [, int $length ] )
        similar_text()  返回两字符串相同字符的数量   int similar_text(str $str1,str $str2)
        strchr()    返回一个字符串在另一个字符串中开始位置到结束的字符串  string strstr ( string $str, string $needle , bool $before_needle )
        strrchr()   返回一个字符串在另一个字符串中最后一次出现位置开始到末尾的字符串    string strrchr ( string $haystack , mixed $needle )
        stristr()   返回一个字符串在另一个字符串中开始位置到结束的字符串，不区分大小写   string stristr ( string $haystack , mixed $needle [, bool $before_needle = false ] )
        strtr() 转换字符串中的某些字符 string strtr ( string $str , string $from , string $to )
        strpos()    寻找字符串中某字符最先出现的位置    int strpos ( string $haystack , mixed $needle [, int $offset = 0 ] )
        stripos()   寻找字符串中某字符最先出现的位置,不区分大小写 int stripos ( string $haystack , string $needle [, int $offset ] )
        strrpos()   寻找某字符串中某字符最后出现的位置   int strrpos ( string $haystack , string $needle [, int $offset = 0 ] )
        strripos()  寻找某字符串中某字符最后出现的位置,不区分大小写    int strripos ( string $haystack , string $needle [, int $offset ] )
        strspn()    返回字符串中首次符合mask的子字符串长度   int strspn ( string $str1 , string $str2 [, int $start [, int $length ]] )
        strcspn()   返回字符串中不符合mask的字符串的长度    int strcspn ( string $str1 , string $str2 [, int $start [, int $length ]] )
        str_word_count()    统计字符串含有的单词数 mix str_word_count(str $str,[])
        strlen()    统计字符串长度 int strlen(str $str)
        count_chars()   统计字符串中所有字母出现次数(0..255)  mixed count_chars ( string $string [, int $mode ] )
        md5()   字符串md5编码    $str = "Hello"; echo md5($str)
        iconv   

        mb_substr   获取字符串的部分    string mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] )
        mb_http_output  设置/获取 HTTP 输出字符编码   mixed mb_http_output ([ string $encoding = mb_http_output() ] )
        mb_strlen   获取字符串的长度    mixed mb_strlen ( string $str [, string $encoding = mb_internal_encoding() ] )
        iconv   字符串按要求的字符编码来转换  string iconv ( string $in_charset , string $out_charset , string $str )
        iconv_substr    截取字符串的部分    
        iconv_get_encoding  获取 iconv 扩展的内部配置变量  
        mb_substr_count 统计字符串出现的次数  
        mb_check_encoding   检查字符串在指定的编码里是否有效    
        mb_strrpos  查找字符串在一个字符串中最后出现的位置 
        mb_split    使用正则表达式分割多字节字符串 
        parse_url   解释URL成为一个数组 */
    }

    public function d(){
       /* 数组函数  功能
        array_shift 弹出数组中的第一个元素
        array_unshift   在数组的开始处压入元素
        array_push  向数组的末尾处压入元素
        array_pop   弹出数组末尾的最后一个元素
        current 读出指针当前位置的值
        key 读出指针当前位置的键
        next    指针向下移
        prev    向上移
        reset   指针到开始处
        end 指针到结束处
        array_combine() 生成一个数组,用一个数组的值作为键名,另一个数组值作为值    
        range() 创建并返回一个包含指定范围的元素的数组。    
        compact()   创建一个由参数所带变量组成的数组    
        array_fill()    用给定的值生成数组   
        array_chunk()   把一个数组分割为新的数组块   
        array_merge()   把两个或多个数组合并为一个数组 
        array_slice()   在数组中根据条件取出一段值，并返回   
        array_diff()    返回两个数组的差集数组 
        array_search()  在数组中搜索给定的值，如果成功则返回相应的键名 
        array_splice()  把数组中的一部分去掉并用其它值取代   
        array_sum() 计算数组中所有值的和  
        in_array()  检查数组中是否存在某个值    
        array_key_exists()  检查给定的键名或索引是否存在于数组中  
        shuffle()   将数组打乱,保留键值  
        count() 计算数组中的单元数目或对象中的属性个数 
        array_flip()    返回一个键值反转后的数组    
        array_keys()    返回数组所有的键,组成一个数组 
        array_values()  返回数组中所有值，组成一个数组 
        array_reverse() 返回一个元素顺序相反的数组   
        array_count_values()    统计数组中所有的值出现的次数  
        array_rand()    从数组中随机抽取一个或多个元素,注意是键名   
        array_unique()  删除重复值，返回剩余数组    
        sort()  按升序对给定数组的值排序,不保留键名  
        rsort() 对数组逆向排序,不保留键名   
        asort() 对数组排序,保持索引关系    
        arsort()    对数组逆向排序,保持索引关系  
        ksort() 按键名对数组排序    
        krsort()    将数组按照键逆向排序  
        natsort()   用自然顺序算法对数组中的元素排序    
        natcasesort()   自然排序,不区分大小写 
        array_filter()  去掉数组中的空元素或者预定元素 
        extract 将键变为变量名，将值变为变量值
        */
    }

    public function e()
    {
       /* /中间写正则/ 正确
        $中间写正则$ 正确
        %中间写正则% 正确
        ^中间写正则^ 正确
        @中间写正则@ 正确
        (中间写正则) 错误
        A中间写正则A 错误

        要匹配/ 的时候，需要把定界符里面的/ 用转义字符转义一下，写成下面的例子：
        / \/ /


        preg_match ( string $正则 , string $字符串 ,[ array &$结果] )
        

        特殊标识的原子

        原子  说明
        \d  匹配一个0-9
        \D  除了0-9以外的所有字符
        \w  a-zA-Z0-9_
        \W  除了0-9A-Za-z_以外的所有字符
        \s  匹配所有空白字符\n \t \r 空格
        \S  匹配所有非空白字符
        [ ] 指定范围的原子
        $zz = '/\d/';
        $string = '我爱喝9你爱不爱喝';
        如if(preg_match($zz,$string,$matches)){
            echo  true;
        }

        元字符 需要借助原子实现 功能说明
        *   是代表匹配前面的一个原子，匹配0次或者任意多次前面的字符。
        +   匹配一次或多前前面的一个字符
        ?   前面的字符可有可无【可选】 有或没有
        .   更标准一些应该把点算作原子。匹配除了\n以外的所有字符
        document/2015-09-04/55e92c421434d   或者。注：它的优先级最低了。
        ^   必须要以抑扬符之后的字符串开始
        $   必须要以$之前的字符结尾
        \b  词边界
        \B  非边界
        {m} 有且只能出现m次
        {n,m}   可以出现n到m次
        {m,}    至少m次，最大次数不限制
        ()  改变优先级或者将某个字符串视为一个整体，匹配到的数据取出来也可以使用它

        如 
        $zz = '/\d+/';
        $string = '我爱喝9你爱不爱喝';
        如if(preg_match($zz,$string,$matches)){
            echo  true;
        }
        

        常用的模式匹配符有：

        模式匹配符   功能
        i   模式中的字符将同时匹配大小写字母.
        m   字符串视为多行
        s   将字符串视为单行,换行符作为普通字符.
        x   将模式中的空白忽略.
        A   强制仅从目标字符串的开头开始匹配.
        D   模式中的美元元字符仅匹配目标字符串的结尾.
        U   匹配最近的字符串.
        放在正则结束之后
        /xxx/i

                */
    }

    public function file(){



        /*模式  说明
        r   只读方式打开，将文件指针指向文件头。
        r+  读写方式打开，将文件指针指向文件头。
        w   写入方式打开，将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建
        w+  读写方式打开，将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建
        a   写入方式打开，将文件指针指向文件末尾。如果文件不存在则尝试创建
        a+  读写方式打开，将文件指针指向文件末尾。如果文件不存在则尝试创建之
        x   创建并以写入方式打开，将文件指针指向文件头。如果文件已存在，则 fopen() 调用失败并返回 FALSE，并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建
        x+  
        创建并以读写方式打开，将文件指针指向文件头。如果文件已存在，则 fopen() 调用失败并返回 FALSE，并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建*/

        //创建了一个临时文件
        //$handle = tmpfile();
        //file_put_contents($handle,"写入数据");
        //重命名文件(源文件,目标文件)
        //rename($filename, $filename2);
        //复制文件
        //copy($filename, $filename2);
        //删除unlink($filename);
        // file_exists ( $指定文件名或者文件路径)
        /*功能：文件是否存在。

        is_readable ( $指定文件名或者文件路径)
        功能：文件是否可读

        is_writeable ( $指定文件名或者文件路径)
        功能：文件是否可写

        is_executable ( $指定文件名或者文件路径)
        功能：文件是否可执行

        is_file ( $指定文件名或者文件路径)
        功能：是否是文件

        is_dir ( $指定文件名或者文件路径)
        功能：是否是目录

        clearstatcache ( void )
        功能：清楚文件的状态缓存
        文件大小filesize($filename)
        截取文件ftruncate($file,20);
        文件上次访问时间fileatime($filename)
        文件创建时间filectime($filename)
        文件修改时间 filemtime($filename)

        锁类型 说明
        LOCK_SH 取得共享锁定（读取的程序）
        LOCK_EX 取得独占锁定（写入的程序
        LOCK_UN 释放锁定（无论共享或独占）
        $fp = fopen("demo.txt", "r+");
        flock($fp, LOCK_EX)
        if (flock($fp, LOCK_EX)) { 

           fwrite($fp, "文件这个时候被我独占了哟\n");

          // 释放锁定
           flock($fp, LOCK_UN);    
        } else {
           echo "锁失败，可能有人在操作，这个时候不能将文件上锁";
        }

        fclose($fp);

        $path_parts = pathinfo('d:/www/index.inc.php');
        echo '文件目录名：'.$path_parts['dirname']."<br />";
        echo '文件全名：'.$path_parts['basename']."<br />";
        echo '文件扩展名：'.$path_parts['extension']."<br />";
        echo '不包含扩展的文件名：'.$path_parts['filename']."<br />"; 

        parse_url ( string $路径 )
        功能：将网址拆解成各个部份

        //定义一个关联数组
        $data = [
               'username'=>'php',
               'area'=>'hubei'
                ];

        //生成query内容 网址?后的参数
        echo http_build_query($data);
        */
        
    }

    public function upload(){
        /*var_dump($_FILES);
        array (size=1)
        'file' => 
        array (size=5)
           //文件名
        'name' => string 'psu.jpg' (length=7) 
          //文件的mime类型
        'type' => string 'image/jpeg' (length=10)                    
          //缓存文件，上传的图片即保存在这里
        'tmp_name' => string 'E:\wamp\tmp\phpC32A.tmp' (length=23)
          //错误码，详见上面错误码介绍
        'error' => int 0                                             
          //上传的文件大小
        'size' => int 225824
        

        if($_FILES['file']['error'] > 0){
           switch ($_FILES['file']['error']) {    //错误码不为0，即文件上传过程中出现了错误
               case '1':
                   echo '文件过大';
                   break;
               case '2':
                   echo '文件超出指定大小';
                   break;
               case '3':
                   echo '只有部分文件被上传';
                   break;
               case '4':
                   echo '文件没有被上传';
                   break;
               case '6':
                   echo '找不到指定文件夹';
                   break;
               case '7':
                   echo '文件写入失败';
                   break;
               default:
                   echo "上传出错<br/>";
           }
        }else{
           //错误码为0，即上传成功，可以进行后续处理，处理流程见下文
            $MAX_FILE_SIZE = 100000;
            if ($_FILES['file']['size'] > $MAX_FILE_SIZE) {
                //判断，如果上传的文件，大小超出了我们给的限制范围，退上传并产生错误提示
                exit("文件超出指定大小");
            }

            //定义允许的后缀名数组
            $myImg = explode('.', $_FILES['file']['name']);
            explode() 将一个字符串用指定的字符切割，并返回一个数组，这里我们将文件名用'.''切割,结果存在$myImg中，文件的后缀名即为数组的最后一个值
            $myImgSuffix = array_pop($myImg);
            if(!in_array($myImgSuffix, ['jpg','png'])){
                exit("文件后缀名不符");
            }

            //数组内容为允许上传的mime类型
            $allowMime = array(
                "image/jpg",
                "image/jpeg",
                "image/pjpeg",
                "image/gif"
            );
            if(!in_array($_FILES['file']['type'], $allowMime)){                      //判断上传文件的mime类型是否在允许的范围内
                exit('文件格式不正确，请检查');
                //如果不在允许范围内，退出上传并返回错误信息
            }

            $name = date("YmdHis",time()).rand(0,9).'.'.$myImgSuffix;

            //使用is_uploaded_file()判断是否是上传文件,
            $path="上传文件夹路径"
            $path = "upload/images/";
            if(is_uploaded_file($_FILEs['file']['tmp_name'])){    
                if(move_uploaded_file($_FILEs['file']['tmp_name'], $path.$name)){
                           //提示文件上传成功
                           echo "上传成功";                                
                }else{

                文件移动失败，检查磁盘是否有足够的空间，或者linux类系统中文件夹是否有足够的操作权限

                           echo '上传失败';                                                
                       }
                   }else{
                       echo '不是上传文件';
                   }

                }
            }
        }
        */
    }
}
